/**
 * 标签页状态管理store
 * 使用Pinia进行状态管理，负责处理浏览器标签页相关的所有操作
 */
import { defineStore } from 'pinia'

import { computed, reactive, ref, watch } from 'vue'
import { createGroup, openGroupNewTab, removeTabsFromGroup } from '@/utils/tab-group'

import { TabOperationsManager } from '@/utils/tab-operations'
// 导入工具函数
import { getAllTabsLinear, isGroup, isTab, moveTabRelativeToAnother } from '@/utils/tab-position'
import { useSidebarStore } from './sidebar'
import { layoutOn } from '@/utils/layoutEvent'
import { extractDomain } from '~shared/utils/urlUtils'
import { useLayoutStore } from '@/windows/layoutBrowser/stores/layout'

// 重新导出类型供其他模块使用

export const useTabStore = defineStore('tab', () => {
  // 使用独立的边栏标签页store
  const sidebarStore = useSidebarStore()
  // tabs字段类型改为TabOrGroup[]，移除tabGroups
  const data: {
    tabs: F2.tab.TabOrGroup[] // 只包含非固定tab和group
    activeTabId: number
  } = reactive({
    tabs: _pre_.browser.getTopTabs(),
    activeTabId: _pre_.browser.getActiveTabId()
  })

  // 同域推进延迟（秒，UI 单位）+ 跨域并发上限，均持久化到本地
  const sameDomainDelaySec = ref<number>(
    Math.min(6, Math.max(0, Number(localStorage.getItem('tab.sameDomainDelaySec') ?? '2')))
  )
  const sameDomainDelayMs = computed(() => sameDomainDelaySec.value * 1000)
  watch(sameDomainDelaySec, v => {
    localStorage.setItem('tab.sameDomainDelaySec', String(Math.min(6, Math.max(0, v || 0))))
  })

  const maxCrossDomainConcurrency = ref<number>(
    Math.min(6, Math.max(1, Number(localStorage.getItem('tab.maxCrossDomainConcurrency') ?? '3')))
  )
  watch(maxCrossDomainConcurrency, v => {
    localStorage.setItem('tab.maxCrossDomainConcurrency', String(Math.min(6, Math.max(1, v || 1))))
  })

  layoutOn('top:created', ts => {
    for (const v of ts) {
      const d = data.tabs.find(t => isTab(t) && t.id === v.id) as F2.tab.Entity | undefined
      if (d) {
        Object.assign(d, v)
        // 历史记录现在由主进程自动管理
      } else {
        // 查找所有 group
        let found = false
        for (const t of data.tabs) {
          if (isGroup(t)) {
            const tabInGroup = t.tabs.find(tab => tab.id === v.id)
            const waitingTab = t.waitingTabs.find(tab => tab.id === v.id)
            if (tabInGroup) {
              Object.assign(tabInGroup, v)

              // 历史记录现在由主进程自动管理
              found = true
              break
            } else if (waitingTab) {
              // 添加到group的等待列表
              t.waitingTabs = t.waitingTabs.filter(tab => tab.id !== v.id)
              t.tabs.push(v)
              found = true
              break
            }
          }
        }
        if (!found) {
          // 检查是否存在source标签
          if (v.source?.type === 'tab' && v.source.id) {
            const inserted = insertAfterSourceTab(v, v.source.id)
            if (!inserted) {
              data.tabs.push(v)
            }
          } else {
            data.tabs.push(v)
          }

          // 历史记录现在由主进程自动管理
        }
      }
    }
  })
  layoutOn('top:inited', tabId => {
    for (const t of data.tabs) {
      if (isGroup(t)) {
        const tab = t.tabs.find(tab => tab.id === tabId)
        if (tab) {
          // 初始化 openingDomains 和 tabIdToDomain
          if (!t.openingDomains) {
            t.openingDomains = new Set<string>()
          }
          if (!t.tabIdToDomain) {
            t.tabIdToDomain = new Map<number, string>()
          }

          // 获取原始域名（从映射中获取，避免URL重定向问题）
          const originalDomain = t.tabIdToDomain.get(tabId)

          // 从正在打开的域名集合中移除当前标签页的原始域名
          if (originalDomain) {
            t.openingDomains.delete(originalDomain)
            // 清理映射记录
            t.tabIdToDomain.delete(tabId)
          }

          // 如果还有等待项，先并发打开跨域的，遇到同域则延迟推进
          if (t.waitingTabs.length > 0) {
            // 立即开启非原域的等待项（遵循跨域并发上限）
            openGroupNewTab(t, {
              skipDomain: originalDomain,
              maxConcurrent: maxCrossDomainConcurrency.value
            })

            // 如果存在同域等待项，延迟一段时间（可配置）再推进同域
            if (originalDomain) {
              const hasSameDomainWaiting = t.waitingTabs.some(
                waitTab => extractDomain(waitTab.url) === originalDomain
              )
              if (hasSameDomainWaiting) {
                console.log('sameDomainDelayMs.value', sameDomainDelayMs.value)
                setTimeout(() => {
                  openGroupNewTab(t, {
                    onlyDomain: originalDomain,
                    maxConcurrent: maxCrossDomainConcurrency.value
                  })
                }, sameDomainDelayMs.value)
              }
            }
          }
          break
        }
      }
    }
  })

  layoutOn('top:update', tab => {
    data.tabs.some(v => {
      if (isTab(v)) {
        if (v.id === tab.id) {
          Object.assign(v, tab)
          return true
        }
      } else {
        const tabInGroup = v.tabs.find(t => t.id === tab.id)
        if (tabInGroup) {
          Object.assign(tabInGroup, tab)
          return true
        }
      }
    })
  })
  const closed = (tabIds: number[]) => {
    if (tabIds.includes(data.activeTabId)) {
      const allTabs = getAllTabsLinear(data.tabs)

      const nextActiveId = TabOperationsManager.getNextActiveTabId(
        data.activeTabId,
        tabIds,
        allTabs
      )
      // 关闭标签页后设置新的活动标签页
      setActiveTab(nextActiveId ?? 0)
    }

    // 清理分组的 openingDomains/tabIdToDomain（处理尚未 inited 就关闭的情况）
    for (const item of data.tabs) {
      if (isGroup(item)) {
        let freed = false
        if (item.tabIdToDomain) {
          for (const id of tabIds) {
            const d = item.tabIdToDomain.get(id)
            if (d) {
              item.openingDomains?.delete(d)
              item.tabIdToDomain.delete(id)
              freed = true
            }
          }
        }
        if (freed && item.waitingTabs.length > 0) {
          // 同域串行：释放域后继续推进等待项（遵循并发上限）
          openGroupNewTab(item, { maxConcurrent: maxCrossDomainConcurrency.value })
        }
      }
    }

    // 主区tabs和group
    data.tabs = TabOperationsManager.filterTabsOrGroups(data.tabs, tabIds)
  }

  layoutOn('top:close', closed)
  layoutOn('left:close', closed)

  layoutOn('switch', tabId => {
    data.activeTabId = tabId
  })

  const layoutStore = useLayoutStore()

  // 创建分组
  layoutOn('group:create', urls => {
    const groupId = createGroup(data.tabs, urls)
    layoutStore.showGroupInspector(groupId)
  })

  // 记录最后关闭的标签页索引，用于恢复功能
  const lastClosedTabIndex = ref<number | null>(null)

  /**
   * 可见标签页数量
   * 计算所有可见标签页的数量（用于宽度计算）
   * 包括：普通标签页 + 展开分组内的标签页
   * 不包括：分组头部（分组头部有固定宽度，不参与动态宽度计算）
   */
  const visibleTabsCount = computed(() => {
    let count = 0
    for (const item of data.tabs) {
      if (isTab(item)) {
        count += 1
      } else if (isGroup(item) && !item.collapsed) {
        count += item.tabs.length
        count += item.waitingTabs.length
      }
      // 收缩的分组不计算其内部标签页
    }
    return count
  })

  // 计算属性：获取当前活动标签页对象
  const activeTab = computed<{ tab: F2.tab.Entity; type: F2.tab.MainControllerType } | undefined>(
    () => {
      // 先在系统固定标签页中查找
      let activeTab = sidebarStore.findLeftTab(data.activeTabId)?.data
      if (activeTab) {
        return {
          tab: activeTab,
          type: 'left'
        }
      }

      // 最后在普通标签页中查找
      data.tabs.some(v => {
        if (isTab(v)) {
          if (v.id === data.activeTabId) {
            activeTab = v
            return true
          }
        } else {
          const tabInGroup = v.tabs.find(tab => tab.id === data.activeTabId)
          if (tabInGroup) {
            activeTab = tabInGroup
            return true
          }
        }
      })
      if (activeTab) {
        return {
          tab: activeTab,
          type: 'top'
        }
      }
      return void 0
    }
  )
  // 计算属性：是否显示地址栏
  const showAddressBar = computed(() => {
    return !activeTab.value
  })

  /**
   * 查找source标签并在其后插入新标签
   * @param newTab 要插入的新标签
   * @param sourceId source标签的ID
   * @returns 是否成功插入
   */
  function insertAfterSourceTab(newTab: F2.tab.Entity, sourceId: number): boolean {
    // 先检查顶层tabs
    const sourceIndex = data.tabs.findIndex(t => isTab(t) && t.id === sourceId)
    if (sourceIndex !== -1) {
      // 在source标签后插入
      data.tabs.splice(sourceIndex + 1, 0, newTab)
      return true
    }

    // 检查分组内的tabs
    for (let i = 0; i < data.tabs.length; i++) {
      const item = data.tabs[i]
      if (item && isGroup(item)) {
        const sourceTabIndex = item.tabs.findIndex(tab => tab.id === sourceId)
        if (sourceTabIndex !== -1) {
          // 在分组内source标签后插入
          item.tabs.splice(sourceTabIndex + 1, 0, newTab)
          return true
        }
      }
    }

    return false
  }

  // 注意：浏览历史记录现在由主进程的 tab.entity.ts 自动管理

  /**
   * 关闭指定的标签页
   * 1. 记录最后关闭的tab索引（在所有可见tab的线性列表中）
   * 2. 如果当前激活tab被关闭，优先激活下一个tab，否则激活上一个tab，否则无tab激活
   * 3. 兼容分组内tab和主区tab，顺序与UI一致
   * @param ids 要关闭的标签页ID数组
   */
  async function closeTabs(ids: number[]) {
    const allTabs = getAllTabsLinear(data.tabs)
    lastClosedTabIndex.value = TabOperationsManager.getLastClosedTabIndex(ids, allTabs)

    _pre_.browser.closeTabs(ids)
  }

  /**
   * 设置活动标签页
   * @param id 要设置为活动的标签页ID
   */
  function setActiveTab(id: number) {
    // 检查是否是边栏标签页且尚未在主进程中创建
    if (id === data.activeTabId) return
    if (id && sidebarStore.isLeftTab(id)) {
      sidebarStore.setActiveTab(id, 'left')
    } else {
      _pre_.browser.setActiveTab(id)
    }
    // 直接更新数据，这里必须加上；否则如果要等主进程通知过来，activeTabId的新值有几帧的延迟
    // 会导致页面闪烁
    data.activeTabId = id
  }

  /**
   * 打开标签页，如果标签页是边栏标签页，则将在边栏中打开； 否则在主区中打开
   * @param tab 要打开的标签页
   * */
  function openTab(tab: F2.tab.Create) {
    if (tab.id && sidebarStore.isRightTab(tab.id)) {
      sidebarStore.setActiveTab(tab.id, 'right')
    } else if (tab.id && sidebarStore.isLeftTab(tab.id)) {
      sidebarStore.setActiveTab(tab.id, 'left')
    } else {
      _pre_.browser.addTab(tab)
    }
  }

  /**
   *从分组移除tab（移回顶层）
   * @param groupId 分组id
   * @param tabIds 要移除的tab id数组
   * @param insertIndex 插入到顶层tabs的索引（可选，默认为原分组位置）
   */
  function removeTabsFromTabGroup(groupId: number, tabIds: number[], insertIndex?: number): void {
    removeTabsFromGroup(data.tabs, groupId, tabIds, insertIndex)
  }

  /**
   * 相对于另一个标签移动
   * @param draggedTabId 要移动的标签页ID或对象
   * @param targetTabId 目标标签页ID或对象,为空时，移动到末尾
   * @param after 是否在目标标签页之后移动
   */
  function moveTabRelativeToAnotherTab(
    draggedTabId: number | F2.tab.TabOrGroup,
    targetTabId: number | undefined,
    after: boolean
  ) {
    moveTabRelativeToAnother(data.tabs, draggedTabId, targetTabId, after)
  }

  /**
   * 关闭所有标签页的独立方法
   */
  const closeAllTabs = () => {
    // 收集所有标签页ID
    const allTabIds = getAllTabsLinear(data.tabs).map(tab => tab.id)

    // 关闭所有标签页
    if (allTabIds.length > 0) {
      closeTabs(allTabIds)
    }
  }

  // requestAnimationFrame(() => {
  //   if (!data.activeTabId) {
  //     setActiveTab(sidebarStore.lastLeftActiveTabId)
  //   }
  // })

  // 导出所有状态和方法
  const storeInstance = {
    tabs: computed(() => data.tabs), // 计算属性：获取所有标签页列表（非固定）
    activeTabId: computed(() => data.activeTabId),
    showAddressBar,
    activeTab,
    normalTabs: computed(() => data.tabs.filter(isTab)),
    visibleTabsCount: computed(() => visibleTabsCount.value),
    lastClosedTabIndex,
    getAllTabsLinear: () => getAllTabsLinear(data.tabs),
    closeTabs,
    setActiveTab,
    openTab,
    removeTabsFromGroup: removeTabsFromTabGroup,
    moveTabRelativeToAnother: moveTabRelativeToAnotherTab,
    closeAllTabs,
    // 配置项（UI 使用秒）
    sameDomainDelaySec,
    maxCrossDomainConcurrency
  }

  // 仅在 E2E 环境将 tabStore 暴露到全局（用于测试）
  // @ts-ignore
  if (globalThis._pre_ && _pre_.isE2E) {
    // @ts-ignore
    ;(globalThis as any).tabStore = storeInstance
  }

  return storeInstance
})
